package com.ts.api.module.channel.controller;

import com.gitee.apanlh.annotation.viewresolver.RequestParamVo;
import com.gitee.apanlh.util.algorithm.digest.MD5;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.model.vo.RequestVO;
import com.gitee.apanlh.web.model.vo.ResultVO;
import com.gitee.apanlh.web.util.ServletUtils;
import com.ts.api.common.constant.BizEnum;
import com.ts.api.common.constant.api.ApiEnum;
import com.ts.api.common.constant.common.SwitchEnum;
import com.ts.api.common.constant.product.ProductPlanOrgTypeEnum;
import com.ts.api.common.context.ChannelContext;
import com.ts.api.common.context.ChannelUserContext;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.exp.BizException;
import com.ts.api.exp.RollBackException;
import com.ts.api.http.feedback.Feedback;
import com.ts.api.module.api.entity.bo.ApiBizMatchBO;
import com.ts.api.module.api.entity.bo.ApiRequiredFlowBO;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.channel.entity.bo.ChannelProductMatchApplyBO;
import com.ts.api.module.channel.entity.bo.ChannelProductMatchBO;
import com.ts.api.module.channel.entity.bo.ChannelProductMatchDisplayBO;
import com.ts.api.module.channel.entity.po.ChannelFlowConfigPO;
import com.ts.api.module.channel.entity.po.ChannelPO;
import com.ts.api.module.channel.entity.po.ChannelLogPO;
import com.ts.api.module.channel.entity.vo.RespChannelProductMatchVO;
import com.ts.api.module.channel.service.ChannelConfigService;
import com.ts.api.module.channel.service.ChannelLogService;
import com.ts.api.module.channel.service.ChannelProductMatchService;
import com.ts.api.module.channel.service.ChannelResetFlowService;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.po.ProductPlanPO;
import com.ts.api.module.product.service.ProductPlanService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 *  H5匹配相关
 */
@RestController
public class ChannelProductController {

    @Autowired
    private ChannelResetFlowService channelResetFlowService;
    @Autowired
    private ChannelProductMatchService channelProductMatchService;
    @Autowired
    private ChannelConfigService channelConfigService;
    @Autowired
    private Feedback feedback;
    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private ProductPlanService productPlanService;
    @Autowired
    private ChannelLogService channelLogService;

    /**
     * 获取信息
     */
    @GetMapping("/channel/product/info")
    public ResultVO<?> info() {
        // 最后分发时间，为null表示在该渠道没有被分发过
        LocalDateTime lastDistributeTime = null;
        // 允许分发，为true表示今天没有分发过
        Boolean allowDistribute = true;

        // 查询日志数据
        ChannelLogPO qo = new ChannelLogPO();
        qo.setLoanChannelId(ChannelContext.getId());
        qo.setType("匹配");
        qo.setLoanUserId(ChannelUserContext.getId());
        ChannelLogPO po = channelLogService.findOne(qo);

        if (Objects.nonNull(po)) {
            // 最后分发时间
            lastDistributeTime = po.getCreateTime();
            // 如果今天有分发过，则不允许分发
            if (LocalDate.now().isEqual(po.getCreateTime().toLocalDate())) {
                allowDistribute = false;
            }
        }

        Map<String, Object> result = new HashMap<>();
        result.put("lastDistributeTime", lastDistributeTime);
        result.put("allowDistribute", allowDistribute);
        return ResultVO.suc(result);
    }

    /**
     *  匹配逻辑
     */
    @PostMapping({"/channel/product/match", "/channel/product/matchOrgV2"})
    public ResultVO<Object> match(@RequestParamVo RequestVO requestVO) {
        int status = 1;
        try {
            this.channelResetFlowService.track();
            //  创建普通匹配计划模式
            ApiBizMatchBO normalPlan = ApiBizMatchBO.createNormalPlan(false);
            //  默认匹配全部
            boolean onlyMatchAll = false;
            //  符合IP屏蔽 只匹配全流程
            if (channelConfigService.hasIpOffModule()) {
                onlyMatchAll = true;
            }
            //  撞库匹配
            ChannelProductMatchBO channelProductMatchBO = channelProductMatchService.dataExchange(normalPlan, onlyMatchAll);

            //  无分发返回
            if (!channelProductMatchBO.getDistributeStatus()) {
                throw new BizException(BizEnum.MATCH_PRODUCT_EMPTY);
            }

            //  获取业务展示实体
            ChannelProductMatchDisplayBO channelProductMatchDisplayBO = channelProductMatchBO.getChannelProductMatchDisplayBO();
            ProductPlanPO productPlanPO = channelProductMatchBO.getProductPlanPO();

            //  是否是回调授权模式
            String callUrl = channelProductMatchDisplayBO.getCallUrl();
            if (ValidParam.isNotEmpty(callUrl)) {
                return ResultVO.suc(RespChannelProductMatchVO.createAuthLink(productPlanPO, channelProductMatchDisplayBO, onlyMatchAll));
            }

            // 匹配到全流程并且该渠道开启二次授权
            ChannelFlowConfigPO channelFlowConfigPO = this.channelConfigService.getFlowConfigByChannelId();
            if (SwitchEnum.hasEnable(channelFlowConfigPO.getEnableSecondAccept())) {
                return ResultVO.suc(RespChannelProductMatchVO.create(productPlanPO, channelProductMatchDisplayBO, onlyMatchAll));
            }

            //  如果是企微链接
            if (ProductPlanOrgTypeEnum.ENTERPRISE_WECHAT.hasType(productPlanPO.getType())) {
                return ResultVO.suc(RespChannelProductMatchVO.create(productPlanPO, channelProductMatchDisplayBO, onlyMatchAll));
            }

            // 全流程进件流程-或半流程进件返url
            ChannelProductMatchApplyBO channelProductMatchApplyBO = channelProductMatchService.apply();
            String applyUrl = channelProductMatchApplyBO.getUrl();
            if (ValidParam.isNotEmpty(applyUrl)) {
                return ResultVO.suc(RespChannelProductMatchVO.createApplyAuthLink(productPlanPO, channelProductMatchDisplayBO, channelProductMatchApplyBO, onlyMatchAll));
            }

            //  获取结果页产品链接
            return ResultVO.suc(RespChannelProductMatchVO.create(productPlanPO, channelProductMatchDisplayBO, onlyMatchAll));
        }catch (Exception e) {
            status = 0;
            throw e;
        } finally {
            ChannelLogPO po = new ChannelLogPO();
            po.setLoanChannelId(ChannelContext.getId());
            po.setType("匹配");
            po.setStatus(status);
            po.setReqUrl(ServletUtils.getRequest().getRequestURI());
            po.setLoanUserId(ChannelUserContext.getId());
            po.setPhone(ChannelUserContext.get().getPhone());
            po.setCreateTime(LocalDateTime.now());
            channelLogService.insert(po);
        }
    }

    /**
     *  在已匹配到机构时，用户点击同意授权
     *  进件流程
     */
    @PostMapping("/channel/product/accept")
    public ResultVO<Object> accept() {
        this.channelResetFlowService.track();
        String phone = ChannelUserContext.get().getPhone();

        ChannelFlowConfigPO channelFlowConfigPO = this.channelConfigService.getFlowConfigByChannelId();

        // 开启二次授权
        if (SwitchEnum.hasEnable(channelFlowConfigPO.getEnableSecondAccept())) {
            //  如果是企微链接
            ChannelPO channelPO = ChannelContext.get();
            ApiRequiredFlowBO apiRequiredFlowBO = ApiRequiredFlowBO.createByChannelId(MD5.create().digestToHex(phone), channelPO.getId());
            ProductApplyFlowPO productApplyFlowPO = apiBizRequiredService.requiredSucDataExchangeFlow(apiRequiredFlowBO);
            if (ValidParam.isNotNull(productApplyFlowPO)) {
                ProductPlanPO productPlanPO = productPlanService.get(productApplyFlowPO.getLoanProductPlanId());
                if (ProductPlanOrgTypeEnum.ENTERPRISE_WECHAT.hasType(productPlanPO.getType())) {
                    return ResultVO.suc(Map.of());
                }
            }

            // 全流程进件流程-或半流程进件返url
            ChannelProductMatchApplyBO channelProductMatchApplyBO = channelProductMatchService.apply();
            //  获取进件返回url
            String applyUrl = channelProductMatchApplyBO.getUrl();
            if (ValidParam.isNotEmpty(applyUrl)) {
                return ResultVO.suc(Map.of("authLink", applyUrl));
            }
            return ResultVO.suc(Map.of());
        }
        return ResultVO.suc(Map.of());
    }

    /**
     *  以机构链接的方式做结算节点-专用接口
     *  企微链接跳转结算节点-进件
     *
     *  @return
     */
    @PostMapping("/channel/product/link/accept")
    public ResultVO<Object> acceptLink() {
        this.channelResetFlowService.track();
        String phone = ChannelUserContext.get().getPhone();

        //  获取撞库流程记录
        ChannelPO channelPO = ChannelContext.get();

        //  获取流程节点
        ApiRequiredFlowBO apiRequiredFlowBO = ApiRequiredFlowBO.createByChannelId(MD5.create().digestToHex(phone), channelPO.getId());
        ProductApplyFlowPO productApplyFlowPO = apiBizRequiredService.requiredSucDataExchangeFlow(apiRequiredFlowBO);

        //  计费节点
        if (ValidParam.isNotNull(productApplyFlowPO)) {
            ProductPlanPO productPlanPO = productPlanService.get(productApplyFlowPO.getLoanProductPlanId());

            //  如果是企微链接
            if (ProductPlanOrgTypeEnum.ENTERPRISE_WECHAT.hasType(productPlanPO.getType())) {
                try {
                    channelProductMatchService.apply();
                } catch (RollBackException rollBackException) {
                    //  如果出现回滚，说明之前已经进件过了，无须计费
                } catch (ApiMsgException apiMsgException) {
                    if(!Eq.object(apiMsgException.getMsgFormat().getCode(), ApiEnum.API_USER_INFO_EXIST.getCode())) {
                        //  不是“已存在”异常，则继续抛出去
                        throw apiMsgException;
                    }
                    //  如果出现回滚，说明之前已经进件过了，无须计费
                }
                return ResultVO.suc(Map.of());
            }
        }
        return ResultVO.suc(Map.of());
    }

    /**
     * 回传
     */
    @PostMapping("/channel/product/feedback")
    public ResultVO<Object> feedback(@RequestParamVo RequestVO requestVO) {
        Object object = this.feedback.feedback(requestVO);
        return ResultVO.suc(object);
    }
}
